package com.dd;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;

public class MorphingAnimation {
    public static final int DURATION_NORMAL = 400;
    public static final int DURATION_INSTANT = 1;

    private OnAnimationEndListener mListener;

    private int mDuration;

    private int mFromWidth;
    private int mToWidth;

    private int mFromColor;
    private int mToColor;

    private int mFromStrokeColor;
    private int mToStrokeColor;

    private float mFromCornerRadius;
    private float mToCornerRadius;

    private float mPadding;

    private Text mView;
    private StrokeGradientDrawable mDrawable;

    public MorphingAnimation(Text viewGroup, StrokeGradientDrawable drawable) {
        mView = viewGroup;
        mDrawable = drawable;

        float v = 0f;
        Integer value = (int) (mFromWidth + (mToWidth - mFromWidth) * v);
        int leftOffset;
        int rightOffset;
        int padding;

        if (mFromWidth > mToWidth) {
            leftOffset = (mFromWidth - value) / 2;
            rightOffset = mFromWidth - leftOffset;
            padding = (int) (mPadding * v);
        } else {
            leftOffset = (mToWidth - value) / 2;
            rightOffset = mToWidth - leftOffset;
            padding = (int) (mPadding - mPadding * v);
        }

        final ShapeElement gradientDrawable = mDrawable.getGradientDrawable();
        gradientDrawable.setBounds(leftOffset + padding, padding, rightOffset - padding, mView.getHeight() - padding);

        gradientDrawable.setRgbColor(getAnimateColor(mFromColor, mToColor, v));

        gradientDrawable.setCornerRadius(mFromCornerRadius + (mToCornerRadius - mFromCornerRadius) * v);
        gradientDrawable.setStroke(
                gradientDrawable.getStrokeWidth(), getAnimateColor(mFromStrokeColor, mToStrokeColor, v));
    }

    public void setDuration(int duration) {
        mDuration = duration;
    }

    public void setListener(OnAnimationEndListener listener) {
        mListener = listener;
    }

    public void setFromWidth(int fromWidth) {
        mFromWidth = fromWidth;
    }

    public void setToWidth(int toWidth) {
        mToWidth = toWidth;
    }

    public void setFromColor(int fromColor) {
        mFromColor = fromColor;
    }

    public void setToColor(int toColor) {
        mToColor = toColor;
    }

    public void setFromStrokeColor(int fromStrokeColor) {
        mFromStrokeColor = fromStrokeColor;
    }

    public void setToStrokeColor(int toStrokeColor) {
        mToStrokeColor = toStrokeColor;
    }

    public void setFromCornerRadius(float fromCornerRadius) {
        mFromCornerRadius = fromCornerRadius;
    }

    public void setToCornerRadius(float toCornerRadius) {
        mToCornerRadius = toCornerRadius;
    }

    public void setPadding(float padding) {
        mPadding = padding;
    }

    public void start() {
        AnimatorValue animatorValue = new AnimatorValue();
        final ShapeElement gradientDrawable = mDrawable.getGradientDrawable();
        animatorValue.setDuration(mDuration);
        animatorValue.setValueUpdateListener(
                (animatorValue1, v) -> {
                    Integer value = (int) (mFromWidth + (mToWidth - mFromWidth) * v);
                    int leftOffset;
                    int rightOffset;
                    int padding;
                    if (mFromWidth > mToWidth) {
                        leftOffset = (mFromWidth - value) / 2;
                        rightOffset = mFromWidth - leftOffset;
                        padding = (int) (mPadding * v);
                    } else {
                        leftOffset = (mToWidth - value) / 2;
                        rightOffset = mToWidth - leftOffset;
                        padding = (int) (mPadding - mPadding * v);
                    }
                    gradientDrawable.setBounds(
                            leftOffset + padding, padding, rightOffset - padding, mView.getHeight() - padding);
                    gradientDrawable.setRgbColor(getAnimateColor(mFromColor, mToColor, v));
                    gradientDrawable.setCornerRadius(mFromCornerRadius + (mToCornerRadius - mFromCornerRadius) * v);
                    gradientDrawable.setStroke(
                            gradientDrawable.getStrokeWidth(),
                            getAnimateColor(mFromStrokeColor, mToStrokeColor, v));
                    mView.invalidate();
                });
        animatorValue.setStateChangedListener(
                new Animator.StateChangedListener() {
                    @Override
                    public void onStart(Animator animator) {}
                    @Override
                    public void onStop(Animator animator) {}
                    @Override
                    public void onCancel(Animator animator) {}
                    @Override
                    public void onEnd(Animator animator) {
                        if (mListener != null) {
                            mListener.onAnimationEnd();
                        }
                    }
                    @Override
                    public void onPause(Animator animator) {}

                    @Override
                    public void onResume(Animator animator) {}
                });
        animatorValue.start();
    }

    public RgbColor getAnimateColor(int from, int to, float value) {
        RgbColor colorFrom = RgbColor.fromArgbInt(from);
        RgbColor colorTo = RgbColor.fromArgbInt(to);
        int red = (int) (colorFrom.getRed() + (colorTo.getRed() - colorFrom.getRed()) * value);
        int blue = (int) (colorFrom.getBlue() + (colorTo.getBlue() - colorFrom.getBlue()) * value);
        int green = (int) (colorFrom.getGreen() + (colorTo.getGreen() - colorFrom.getGreen()) * value);
        int alpha = (int) (colorFrom.getAlpha() + (colorTo.getAlpha() - colorFrom.getAlpha()) * value);
        RgbColor mCurrentColorRgb = new RgbColor(red, green, blue, alpha);
        return mCurrentColorRgb;
    }
}
